﻿#include "catimgui.h"
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"

#include "../../libcat/include/cat.hpp"
#include "../../libcat/include/util/base.hpp"
#include "../../libcat/include/util/json.h"
#include "../../libcat/include/util/jsoncpp.cpp"

#include "../../liblive2d/include/catlive2d.hpp"
#include "cat-client.hpp"
#include "portable-file-dialogs.h"

#include <SFML/Graphics.hpp>
#include <fstream>

// About Desktop OpenGL function loaders:
//  Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers.
//  Helper libraries are often used for this purpose! Here we are supporting a few common ones (gl3w, glew, glad).
//  You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own.
#if defined(IMGUI_IMPL_OPENGL_LOADER_GL3W)
#include <GL/gl3w.h>            // Initialize with gl3wInit()
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLEW)
#include <GL/glew.h>            // Initialize with glewInit()
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD)
#include <glad/glad.h>          // Initialize with gladLoadGL()
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING2)
#define GLFW_INCLUDE_NONE       // GLFW including OpenGL headers causes ambiguity or multiple definition errors.
#include <glbinding/Binding.h>  // Initialize with glbinding::Binding::initialize()
#include <glbinding/gl/gl.h>
using namespace gl;
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING3)
#define GLFW_INCLUDE_NONE       // GLFW including OpenGL headers causes ambiguity or multiple definition errors.
#include <glbinding/glbinding.h>// Initialize with glbinding::initialize()
#include <glbinding/gl/gl.h>
using namespace gl;
#else
#include IMGUI_IMPL_OPENGL_LOADER_CUSTOM
#endif

// Include glfw3.h after our OpenGL definitions
#include <GLFW/glfw3.h>
#include <imgui_internal.h>
#include "../../libcat/include/util/platform.hpp"

// [Win32] Our example includes a copy of glfw3.lib pre-compiled with VS2010 to maximize ease of testing and compatibility with old VS compilers.
// To link with VS2010-era libraries, VS2015+ requires linking with legacy_stdio_definitions.lib, which we do using this pragma.
// Your own project should not be affected, as you are likely to link with a newer binary of GLFW that is adequate for your version of Visual Studio.
#if defined(_MSC_VER) && (_MSC_VER >= 1900) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS)
#pragma comment(lib, "legacy_stdio_definitions")
#endif

static void glfw_error_callback(int error, const char* description)
{
    fprintf(stderr, "Glfw Error %d: %s\n", error, description);
}


static void HelpMarker(const char* desc)
{
    ImGui::TextDisabled("(?)");
    if (ImGui::IsItemHovered())
    {
        ImGui::BeginTooltip();
        ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
        ImGui::TextUnformatted(desc);
        ImGui::PopTextWrapPos();
        ImGui::EndTooltip();
    }
}
char* LoadFile(const char* path)
{
#if _WIN64

    //fix open wchar file path
    int wchars_num = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0);
    wchar_t* wstr = new wchar_t[wchars_num];
    MultiByteToWideChar(CP_UTF8, 0, path, -1, wstr, wchars_num);

    int size = 0;
    struct _stat64 statBuf;
    if (_wstat64(wstr, &statBuf) == 0)
    {
        size = statBuf.st_size;
    }
    else {
        size = 0;
    }
#else
    int wchars_num = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0);
    wchar_t* wstr = new wchar_t[wchars_num];
    MultiByteToWideChar(CP_UTF8, 0, path, -1, wstr, wchars_num);

    int size = 0;
    struct _stat32 statBuf;
    if (_wstat32(wstr, &statBuf) == 0) {
        size = statBuf.st_size;
    }
    else {
        size = 0;
    }
#endif // X64
    std::fstream file;
    char* buf = (char*)malloc(size);

    file.open(wstr, std::ios::in | std::ios::binary);
    if (!file.is_open())
    {
        return NULL;
    }
    file.read(buf, size);
    file.close();
    delete wstr;
    return buf;
}

static void load_module_decelaration(cat_data* cfg,int module_id) {
    std::string standard_module_path;
    for (auto entry = cfg->json["plugins"]["mode_ex"].begin(); entry != cfg->json["plugins"]["mode_ex"].end(); entry++) {
        if (module_id == (*entry)["module_id"].asInt()) {
            standard_module_path = (*entry)["module_data_path"].asString();
            break;
        }       
    }
    const char* data = LoadFile(standard_module_path.c_str());
    if (data == NULL)
    {
        return;
    }

    JSONCPP_STRING error;
    Json::CharReaderBuilder json_builder;
    Json::Value root;
    Json::CharReader* json_reader = json_builder.newCharReader();
    bool parsingSuccessful = json_reader->parse(data, data + strlen(data), &root, &error);
    if (!parsingSuccessful) {
        return;
    }
    delete json_reader;
    delete data;

    cfg->json["decoration"]["window_size"][0] = root["decoration"]["window_size"][0].asInt();
    cfg->json["decoration"]["window_size"][1] = root["decoration"]["window_size"][1].asInt();

    cfg->json["decoration"]["l2d_correct"]= root["decoration"]["l2d_correct"].asFloat();
    cfg->json["decoration"]["l2d_offset"][0]= root["decoration"]["l2d_offset"][0].asFloat();
    cfg->json["decoration"]["l2d_offset"][1]= root["decoration"]["l2d_offset"][1].asFloat();

    cfg->json["decoration"]["armLineColor"][0] = root["decoration"]["armLineColor"][0].asInt();
    cfg->json["decoration"]["armLineColor"][1] = root["decoration"]["armLineColor"][1].asInt();
    cfg->json["decoration"]["armLineColor"][2] = root["decoration"]["armLineColor"][2].asInt();

    cfg->json["decoration"]["hand_offset"][0] = root["decoration"]["hand_offset"][0].asInt();
    cfg->json["decoration"]["hand_offset"][1] = root["decoration"]["hand_offset"][1].asInt();;

}

static void DataSender(CatClient &client,int action,cat_data *data) {
    Json::FastWriter fastWriter;
    std::string output = fastWriter.write(data->json);
    client.SendData(action,(char*)output.c_str(),output.size());
}
static bool updateJson(Json::Value& cfg_default, Json::Value& cfg)
{
    bool is_update = true;
    for (const auto& key : cfg.getMemberNames())
        if (cfg_default.isMember(key))
        {
            if (cfg_default[key].type() != cfg[key].type())
            {
                blog(LOG_ERROR, "Value type error in config.json");
                return false;
            }
            if (cfg_default[key].isArray())
                for (Json::Value& v : cfg[key])
                    if (v.type() != cfg_default[key][0].type())
                    {
                        blog(LOG_ERROR, "Value type error in config.json");
                        return false;
                    }
            if (cfg_default[key].isObject())
                is_update &= updateJson(cfg_default[key], cfg[key]);
            else
                cfg_default[key] = cfg[key];
        }
    return is_update;
}
void catimgui::Run(int port)
{
    CatClient client;
    client.SetClientPort(port);

    cat_live2d_initailize();

    const char* glsl_version = "#version 130";
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
    glfwWindowHint(GLFW_VISIBLE, GL_TRUE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
    // Create window with graphics context
    GLFWwindow* window = glfwCreateWindow(1280, 720, u8"Bongo Cat 设置", NULL, NULL);
    if (window == NULL)
        return;
    glfwMakeContextCurrent(window);
    glfwSwapInterval(1); // Enable vsync

    sf::Image icon;
    icon.loadFromFile("resources/bongocat_mver2.png"); 
    GLFWimage icons[1];
    icons[0].width = icon.getSize().x;
    icons[0].height = icon.getSize().y;
    icons[0].pixels = (unsigned char*)icon.getPixelsPtr();
    glfwSetWindowIcon(window, 1, icons);

#if defined(IMGUI_IMPL_OPENGL_LOADER_GL3W)
    bool err = gl3wInit() != 0;
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLEW)
    bool err = glewInit() != GLEW_OK;
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD)
    bool err = gladLoadGL() == 0;
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING2)
    bool err = false;
    glbinding::Binding::initialize();
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING3)
    bool err = false;
    glbinding::initialize([](const char* name) { return (glbinding::ProcAddress)glfwGetProcAddress(name); });
#else
    bool err = false; // If you use IMGUI_IMPL_OPENGL_LOADER_CUSTOM, your loader is likely to requires some form of initialization.
#endif
    if (err)
    {
        fprintf(stderr, "Failed to initialize OpenGL loader!\n");
        return;
    }

    // Setup Dear ImGui context
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO(); (void)io;
    ImFont* font = io.Fonts->AddFontFromFileTTF("resources/cat.ttf", 22.0f, NULL, io.Fonts->GetGlyphRangesChineseFull());
    //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
    //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls

    // Setup Dear ImGui style
    ImGui::StyleColorsDark();
    //ImGui::StyleColorsClassic();

    // Setup Platform/Renderer bindings
    ImGui_ImplGlfw_InitForOpenGL(window, true);
    ImGui_ImplOpenGL3_Init(glsl_version);

    
    ImGuiWindowFlags window_flags = 0;
    window_flags |= ImGuiWindowFlags_NoMove;
    window_flags |= ImGuiWindowFlags_NoCollapse;
    window_flags |= ImGuiWindowFlags_NoResize;
    cat_data* cfg =cat_data_create_from_json_file("config.ini");
      
    int mode = cfg->json["plugins"]["mode"].asInt();
    /***********************************************/
    //背景颜色
    ImVec4 clear_color = ImVec4(static_cast<float>(cfg->json["main_decoration"]["rgb"][0].asInt())/255.0
        ,static_cast<float>(cfg->json["main_decoration"]["rgb"][1].asInt()) / 255.0
        ,static_cast<float>(cfg->json["main_decoration"]["rgb"][2].asInt()) / 255.0
        ,static_cast<float>(cfg->json["main_decoration"]["rgb"][3].asInt()) / 255.0);
    /***********************************************/
    //窗口设置
    int framerateLimit = cfg->json["main_decoration"]["framerateLimit"].asInt();
    bool deskPet = cfg->json["main_decoration"]["desktop_pet"].asBool();
    bool topWindow = cfg->json["main_decoration"]["topWindow"].asBool();
    
    /***********************************************/
    //鼠标设置;
    bool mousePass = cfg->json["main_decoration"]["is_mouse_through"].asBool();
    bool mouse_horizontal_flip = cfg->json["main_decoration"]["mouse_horizontal_flip"].asBool();
    bool mouse_vertical_flip = cfg->json["main_decoration"]["mouse_vertical_flip"].asBool();
    bool mouse_force_move = cfg->json["main_decoration"]["mouse_force_move"].asBool();
    float mouse_speed = cfg->json["main_decoration"]["mouse_speed"].asFloat();
    /***********************************************/
    //声音设置
    bool silent = cfg->json["main_decoration"]["silent"].asBool();
    int elem1 = cfg->json["main_decoration"]["sound_keep"].asBool() ? 0 : 1; 
    /***********************************************/
    //其他设置
    int elem = cfg->json["main_decoration"]["motion_keep"].asBool() ? 0 : 1;
    /***********************************************/
    
    bool l2d = cfg->json["main_decoration"]["l2d"].asBool();
    float l2d_spead = cfg->json["main_decoration"]["l2d_spead"].asFloat();  
    bool l2d_random_motion = cfg->json["main_decoration"]["l2d_random_motion"].asBool();
    bool l2d_random_expression = cfg->json["main_decoration"]["l2d_random_expression"].asBool();

    /***********************************************/
    load_module_decelaration(cfg,mode);

    float l2d_scale = cfg->json["decoration"]["l2d_correct"].asFloat();
    float l2d_position_x = cfg->json["decoration"]["l2d_offset"][0].asFloat();
    float l2d_position_y = cfg->json["decoration"]["l2d_offset"][1].asFloat();
  
    ImVec4 rightarmLine = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
    rightarmLine.x = static_cast<float>(cfg->json["decoration"]["armLineColor"][0].asInt()) / 255.0;
    rightarmLine.y = static_cast<float>(cfg->json["decoration"]["armLineColor"][1].asInt()) / 255.0;
    rightarmLine.z = static_cast<float>(cfg->json["decoration"]["armLineColor"][2].asInt()) / 255.0;

    int hand_position_x = cfg->json["decoration"]["hand_offset"][0].asInt();
    int hand_position_y = cfg->json["decoration"]["hand_offset"][1].asInt(); 

    static std::shared_ptr<pfd::open_file> open_file;
    static bool saveFile = false;
    static bool saveFileError = false;

    sf::Clock heart;
    heart.restart();

    while (true)
    {
        bool isHostLive = true;
        if (heart.getElapsedTime() > sf::seconds(1))
        {
            isHostLive = client.SendData(HeartBeat, "", 0);
            heart.restart();
        }
        if (!isHostLive)
            glfwSetWindowShouldClose(window,true);

        glfwPollEvents();

        // Start the Dear ImGui frame
        ImGui_ImplOpenGL3_NewFrame();
        ImGui_ImplGlfw_NewFrame();
        ImGui::NewFrame();

        //这里放ui的逻辑
        if(!glfwWindowShouldClose(window))
        {
            if (ImGui::BeginMainMenuBar())
            {
                if (ImGui::BeginMenu(u8"选项"))
                {
                   
                    if (ImGui::MenuItem(u8"日志", "by w w w")) {}
                    ImGui::EndMenu();
                }                 
                ImGui::EndMainMenuBar();
            }   

            ImGui::Begin(u8"模式",0,window_flags);
            {
                ImGui::Text(u8"模式列表:");   

                for (auto entry = cfg->json["plugins"]["mode_ex"].begin(); entry != cfg->json["plugins"]["mode_ex"].end(); entry++) {
                    if (mode == (*entry)["module_id"].asInt()) {
                        ImGui::Text(u8"当前模式:%s", (*entry)["module_name"].asCString()); 
                        if (!(*entry)["active"].asBool()) {
                            (*entry)["active"] = true;
                            load_module_decelaration(cfg,mode);

                            l2d_scale = cfg->json["decoration"]["l2d_correct"].asFloat();
                            l2d_position_x = cfg->json["decoration"]["l2d_offset"][0].asFloat();
                            l2d_position_y = cfg->json["decoration"]["l2d_offset"][1].asFloat();
                            
                            rightarmLine.x = static_cast<float>(cfg->json["decoration"]["armLineColor"][0].asInt()) / 255.0;
                            rightarmLine.y = static_cast<float>(cfg->json["decoration"]["armLineColor"][1].asInt()) / 255.0;
                            rightarmLine.z = static_cast<float>(cfg->json["decoration"]["armLineColor"][2].asInt()) / 255.0;

                            hand_position_x = cfg->json["decoration"]["hand_offset"][0].asInt();
                            hand_position_y = cfg->json["decoration"]["hand_offset"][1].asInt();

                            DataSender(client, ModeChange, cfg);
                        }                                                                 
                    }
                    else {
                        (*entry)["active"] = false;
                    }
                }
                ImGui::Separator();

                for (auto entry = cfg->json["plugins"]["mode_ex"].begin(); entry != cfg->json["plugins"]["mode_ex"].end();entry++) {
                    
                    ImGui::Text(u8"模式名称:%s",(*entry)["module_name"].asCString());
                    std::string config_file = (*entry)["module_data_path"].asString().substr((*entry)["module_data_path"].asString().find_last_of("\\")+1, (*entry)["module_data_path"].asString().length() - (*entry)["module_data_path"].asString().find("\\"));
                    if(config_file.length()!=0)
                        ImGui::Text(u8"配置文件:\n%s", config_file.c_str());
                    else
                    {
                        ImGui::Text(u8"配置文件:\n%s", (*entry)["module_data_path"].asCString());
                    }
                    ImGui::Text(u8"状态:%s", (*entry)["active"].asBool() ? u8"已启动" : u8"未启动");                                     

                    if (!(*entry)["active"].asBool()) 
                    {
                        std::string open_text = u8"启动:";
                        open_text += (*entry)["module_name"].asString();
                        if (ImGui::Button(open_text.c_str())) {
                            (*entry)["active"] = true;
                            mode = (*entry)["module_id"].asInt();
                            cfg->json["plugins"]["mode"] = mode;
                            load_module_decelaration(cfg, mode);

                            l2d_scale = cfg->json["decoration"]["l2d_correct"].asFloat();
                            l2d_position_x = cfg->json["decoration"]["l2d_offset"][0].asFloat();
                            l2d_position_y = cfg->json["decoration"]["l2d_offset"][1].asFloat();

                            rightarmLine.x = static_cast<float>(cfg->json["decoration"]["armLineColor"][0].asInt()) / 255.0;
                            rightarmLine.y = static_cast<float>(cfg->json["decoration"]["armLineColor"][1].asInt()) / 255.0;
                            rightarmLine.z = static_cast<float>(cfg->json["decoration"]["armLineColor"][2].asInt()) / 255.0;

                            hand_position_x = cfg->json["decoration"]["hand_offset"][0].asInt();
                            hand_position_y = cfg->json["decoration"]["hand_offset"][1].asInt();

                            DataSender(client, ModeChange, cfg);
                        }
                    }

                    if ((*entry)["active"].asBool()) {
                        if (ImGui::Button(u8"资源重载")) {
                            load_module_decelaration(cfg, mode);

                            l2d_scale = cfg->json["decoration"]["l2d_correct"].asFloat();
                            l2d_position_x = cfg->json["decoration"]["l2d_offset"][0].asFloat();
                            l2d_position_y = cfg->json["decoration"]["l2d_offset"][1].asFloat();

                            rightarmLine.x = static_cast<float>(cfg->json["decoration"]["armLineColor"][0].asInt()) / 255.0;
                            rightarmLine.y = static_cast<float>(cfg->json["decoration"]["armLineColor"][1].asInt()) / 255.0;
                            rightarmLine.z = static_cast<float>(cfg->json["decoration"]["armLineColor"][2].asInt()) / 255.0;

                            hand_position_x = cfg->json["decoration"]["hand_offset"][0].asInt();
                            hand_position_y = cfg->json["decoration"]["hand_offset"][1].asInt();

                            DataSender(client, Reload, cfg);

                        }

                        ImGui::SameLine();  
                        ImGui::PushItemFlag(ImGuiItemFlags_Disabled, (bool)open_file);
                        if (ImGui::Button(u8"重设配置文件")) {
                            std::vector<std::string> filters = {  "json","*.json" };
                            open_file = std::make_shared<pfd::open_file>(u8"选择猫咪配置文件", "data", filters);
                           
                            //
                        } 
                        if (open_file && open_file->ready())
                        {
                            auto result = open_file->result();
                            if (result.size())
                                (*entry)["module_data_path"]= result[0];
                            open_file = nullptr;
                            load_module_decelaration(cfg, mode);

                            l2d_scale = cfg->json["decoration"]["l2d_correct"].asFloat();
                            l2d_position_x = cfg->json["decoration"]["l2d_offset"][0].asFloat();
                            l2d_position_y = cfg->json["decoration"]["l2d_offset"][1].asFloat();

                            rightarmLine.x = static_cast<float>(cfg->json["decoration"]["armLineColor"][0].asInt()) / 255.0;
                            rightarmLine.y = static_cast<float>(cfg->json["decoration"]["armLineColor"][1].asInt()) / 255.0;
                            rightarmLine.z = static_cast<float>(cfg->json["decoration"]["armLineColor"][2].asInt()) / 255.0;

                            hand_position_x = cfg->json["decoration"]["hand_offset"][0].asInt();
                            hand_position_y = cfg->json["decoration"]["hand_offset"][1].asInt();

                            DataSender(client, Reload, cfg);
                        }
                        ImGui::PopItemFlag();
                    }                    
                    ImGui::Separator();
                }             
            }                                   

            ImGui::End();           
            ImGui::Begin(u8"插件", 0, window_flags);
            {
                ImGui::Text(u8"插件列表:");
                ImGui::Separator();
                for (auto entry = cfg->json["plugins"]["module"].begin(); entry != cfg->json["plugins"]["module"].end(); entry++) {

                    ImGui::Text(u8"插件名称:%s", (*entry)["module_name"].asCString());
                    ImGui::Text(u8"状态:%s", (*entry)["active"].asBool() ? u8"已启动" : u8"未启动");

                    if ((*entry)["active"].asBool()) {
                        std::string close_text = u8"关闭:";
                        close_text += (*entry)["module_name"].asString();
                        if (ImGui::Button(close_text.c_str())) {
                            (*entry)["active"] = false;
                            DataSender(client, Update, cfg);
                        }
                    }
                    else {
                        std::string open_text = u8"启动:";
                        open_text += (*entry)["module_name"].asString();
                        if (ImGui::Button(open_text.c_str())) {
                            (*entry)["active"] = true;
                            DataSender(client, Update, cfg);
                        }
                    }

                    ImGui::Separator();
                }
            }
            ImGui::End();

            ImGui::Begin(u8"基础设置", 0, window_flags);
            {
                ImGui::Text(u8"窗口设置");
                if (ImGui::SliderInt(u8"帧率", &framerateLimit, 10, 240, u8"FPS X %d")) {
                    cfg->json["main_decoration"]["framerateLimit"] = framerateLimit;
                    DataSender(client, WindowChange, cfg);
                }

                if (ImGui::Checkbox(u8"桌宠模式", &deskPet)) {
                    cfg->json["main_decoration"]["desktop_pet"]= deskPet;
                    if (!deskPet) {
                        mousePass = false;
                        cfg->json["main_decoration"]["is_mouse_through"] = mousePass;
                    }
                    DataSender(client, WindowChange, cfg);
                }

                if (deskPet) {
                    if (ImGui::Checkbox(u8"鼠标穿透", &mousePass)) {
                        cfg->json["main_decoration"]["is_mouse_through"] = mousePass;
                        DataSender(client, Update, cfg);
                    }
                }

                if (ImGui::Checkbox(u8"窗口置顶", &topWindow)) {
                        cfg->json["main_decoration"]["topWindow"] = topWindow;
                        DataSender(client, WindowChange, cfg);
                } 

                ImGui::Text(u8"鼠标设置");

                if (ImGui::Checkbox(u8"鼠标移动水平翻转", &mouse_horizontal_flip)) {
                    cfg->json["main_decoration"]["mouse_horizontal_flip"] = mouse_horizontal_flip;
                    DataSender(client, Update, cfg);
                }

                if (ImGui::Checkbox(u8"鼠标移动垂直翻转", &mouse_vertical_flip)) {
                    cfg->json["main_decoration"]["mouse_vertical_flip"] = mouse_vertical_flip;
                    DataSender(client, Update, cfg);
                }

                if (ImGui::Checkbox(u8"鼠标强制移动", &mouse_force_move)) {
                    cfg->json["main_decoration"]["mouse_force_move"] = mouse_force_move;
                    DataSender(client, Update, cfg);
                } 
                ImGui::SameLine(); HelpMarker(u8"3D游戏锁鼠标移动时,计算鼠标相对移动距离");
                if (mouse_force_move) 
                {
                    if (ImGui::SliderFloat(u8"鼠标速度", &mouse_speed, 0.1f, 10.0f, u8"速度 X %.3f")) {
                        cfg->json["main_decoration"]["mouse_speed"] = mouse_speed;
                        DataSender(client, Update, cfg);
                    }
                }
               
                           
                ImGui::Text(u8"声音设置");
                if (ImGui::Checkbox(u8"静音", &silent)) {
                    cfg->json["main_decoration"]["silent"] = silent;
                    DataSender(client, Update, cfg);
                } 

                const char* elems_names1[2] = {  u8"重新播放",u8"同时播放"};
                const char* elem_name1 = (elem1 >= 0 && elem1 < 2) ? elems_names1[elem1] : "Unknown";
                if (ImGui::SliderInt(u8"声音播放方式", &elem1, 0, 2 - 1, elem_name1)) {
                    elem1 == 0 ? cfg->json["main_decoration"]["sound_keep"] = true : cfg->json["main_decoration"]["sound_keep"] = false;
                    DataSender(client, Update, cfg);
                }
                            
                ImGui::Text(u8"其他设置");
                const char* elems_names[2] = {  u8"按键取消",u8"松手取消"};
                const char* elem_name = (elem >= 0 && elem < 2) ? elems_names[elem] : "Unknown";
                if (ImGui::SliderInt(u8"表情取消方式", &elem, 0, 2 - 1, elem_name)) {
                    elem == 0 ? cfg->json["main_decoration"]["motion_keep"] = true : cfg->json["main_decoration"]["motion_keep"] = false;
                    DataSender(client, Update, cfg);
                }                           
            }
            ImGui::End();                   

            ImGui::Begin(u8"Live2D设置", 0, window_flags);          
            {
                if (ImGui::Checkbox(u8"使用live2D", &l2d)) {
                    cfg->json["main_decoration"]["l2d"] = l2d; 
                    DataSender(client, Update, cfg);

                }
                ImGui::Text(u8"按住ctrl进行精确修改");
                if (!l2d) {
                    if (ImGui::ColorEdit3(u8"手臂边缘色彩", (float*)&rightarmLine)) 
                    {
                        cfg->json["decoration"]["armLineColor"][0] = static_cast<int>(rightarmLine.x * 255);
                        cfg->json["decoration"]["armLineColor"][1] = static_cast<int>(rightarmLine.y * 255);
                        cfg->json["decoration"]["armLineColor"][2] = static_cast<int>(rightarmLine.z * 255);
                        DataSender(client, Update, cfg);
                    }
                    if (ImGui::SliderInt(u8"手X坐标", &hand_position_x, -50, 50, u8" x轴偏移 %d")) {
                        cfg->json["decoration"]["hand_offset"][0] = hand_position_x;
                        DataSender(client, Update, cfg);
                    }
                    if (ImGui::SliderInt(u8"手Y坐标", &hand_position_y, -50, 50, u8" y轴偏移 %d")) {
                        cfg->json["decoration"]["hand_offset"][1] = hand_position_y;
                        DataSender(client, Update, cfg);
                    }
                }
                else {
                        if (ImGui::Checkbox(u8"随机动作", &l2d_random_motion)) {
                            cfg->json["main_decoration"]["l2d_random_motion"] = l2d_random_motion;
                            if (!l2d_random_motion) {
                                cfg->json["main_decoration"]["l2d_random_expression"] = false;
                                l2d_random_expression = false;
                            }
                            DataSender(client, Update, cfg);
                        }
                        ImGui::SameLine(); HelpMarker(u8"注意！此选项会播放所有动作组里的动作");

                        if(l2d_random_motion)
                        if (ImGui::Checkbox(u8"随机表情", &l2d_random_expression)) {
                            cfg->json["main_decoration"]["l2d_random_expression"] = l2d_random_expression;
                            DataSender(client, Update, cfg);
                        }                 
                        if (ImGui::SliderFloat(u8"运动速度", &l2d_spead, 0.0f, 10.0f, u8"速度 X %.4f", 2.0f))
                        {
                            cfg->json["main_decoration"]["l2d_spead"] = l2d_spead;
                            DataSender(client, Update, cfg);
                        }
                       
                        if (ImGui::SliderFloat(u8"伸缩", &l2d_scale, 0.0f, 10.0f, "%.4f", 4.0f))
                        {
                            cfg->json["decoration"]["l2d_correct"] = l2d_scale;
                            DataSender(client, Update, cfg);
                        }

                        if (ImGui::SliderFloat(u8"x 坐标", &l2d_position_x, -1.0f, 1.0f, "%f", 5.0f))
                        {
                            cfg->json["decoration"]["l2d_offset"][0] = l2d_position_x;
                            DataSender(client, Update, cfg);
                        }
                        if (ImGui::SliderFloat(u8"y 坐标", &l2d_position_y, -1.0f, 1.0f, "%f", 5.0f)) {
                            cfg->json["decoration"]["l2d_offset"][1] = l2d_position_y;
                            DataSender(client, Update, cfg);
                        }
                        
                    }   

                if (ImGui::Button(u8"保存设置到json文件"))
                {
                    
                    std::string standard_module_path;
                    for (auto entry = cfg->json["plugins"]["mode_ex"].begin(); entry != cfg->json["plugins"]["mode_ex"].end(); entry++) {
                        if (mode == (*entry)["module_id"].asInt()) {
                            standard_module_path = (*entry)["module_data_path"].asString();
                            break;
                        }
                    }
                    const char* data = LoadFile(standard_module_path.c_str());
                    if (data != NULL) {
                        saveFile = true;
                        JSONCPP_STRING error;
                        Json::CharReaderBuilder json_builder;
                        Json::Value root;
                        Json::CharReader* json_reader = json_builder.newCharReader();
                        bool parsingSuccessful = json_reader->parse(data, data + strlen(data), &root, &error);
                        if (!parsingSuccessful) {
                            return;
                        }
                        delete json_reader;
                        delete data;
                        updateJson(root, cfg->json); 

                        int wchars_num = MultiByteToWideChar(CP_UTF8, 0, standard_module_path.c_str(), -1, NULL, 0);
                        wchar_t* wstr = new wchar_t[wchars_num];
                        MultiByteToWideChar(CP_UTF8, 0, standard_module_path.c_str(), -1, wstr, wchars_num);

                        std::ofstream os;
                        os.open(wstr, std::ios::out | std::ios::trunc);
                        if (os.good()) {
                            Json::StreamWriterBuilder builder;
                            std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
                            writer->write(root, &os);                        
                        }
                        os.close();                     
                        delete[] wstr;

                                     
                    }
                    else {
                        saveFileError = true;
                    }
                    
                }
            }                    
            ImGui::End();  
            

            ImGui::Begin(u8"背景设置", 0, window_flags);
            {
                static ImVec4 color = ImVec4(clear_color.x, clear_color.y, clear_color.z, clear_color.z);

                static bool alpha_preview = true;
                static bool alpha_half_preview = false;
                static bool drag_and_drop = true;
                static bool options_menu = true;
                static bool hdr = true;
                ImGuiColorEditFlags misc_flags = (hdr ? ImGuiColorEditFlags_HDR : 0) | (drag_and_drop ? 0 : ImGuiColorEditFlags_NoDragDrop) | (alpha_half_preview ? ImGuiColorEditFlags_AlphaPreviewHalf : (alpha_preview ? ImGuiColorEditFlags_AlphaPreview : 0)) | (options_menu ? 0 : ImGuiColorEditFlags_NoOptions);
             
                ImGui::Text(u8"颜色选取");
                static bool alpha = true;
                static bool alpha_bar = true;
                static bool side_preview = true;
                static bool ref_color = false;
                static ImVec4 ref_color_v(1.0f, 0.0f, 1.0f, 0.5f);
                static int display_mode = 0;
                static int picker_mode = 0;
                ImGui::Checkbox(u8"设置透明度", &alpha); 
                ImGui::SameLine(); HelpMarker(u8"设置背景颜色的透明度");
                alpha_bar = alpha;               
                
                ImGui::Checkbox(u8"预览", &side_preview);
                ImGui::Combo(u8"显示模式", &display_mode, u8"自动\0无\0RGB模式\0HSV模式\0十六进制色值\0");
                ImGui::SameLine(); HelpMarker(u8"显示颜色的数字 RGB HSV 或 16进制" );
                ImGui::Combo(u8"选择模式", &picker_mode, u8"自动\0Hue bar + SV rect\0Hue wheel + SV triangle\0");
                ImGui::SameLine(); HelpMarker(u8"点击选择器选择背景颜色");
                ImGuiColorEditFlags flags = misc_flags;
                if (!alpha)            flags |= ImGuiColorEditFlags_NoAlpha;        // This is by default if you call ColorPicker3() instead of ColorPicker4()
                if (alpha_bar)         flags |= ImGuiColorEditFlags_AlphaBar;
                if (!side_preview)     flags |= ImGuiColorEditFlags_NoSidePreview;
                if (picker_mode == 1)  flags |= ImGuiColorEditFlags_PickerHueBar;
                if (picker_mode == 2)  flags |= ImGuiColorEditFlags_PickerHueWheel;
                if (display_mode == 1) flags |= ImGuiColorEditFlags_NoInputs;       // Disable all RGB/HSV/Hex displays
                if (display_mode == 2) flags |= ImGuiColorEditFlags_DisplayRGB;     // Override display mode
                if (display_mode == 3) flags |= ImGuiColorEditFlags_DisplayHSV;
                if (display_mode == 4) flags |= ImGuiColorEditFlags_DisplayHex;
                if (ImGui::ColorPicker4(u8"色彩##4", (float*)&color, flags, ref_color ? &ref_color_v.x : NULL)) {
                    cfg->json["main_decoration"]["rgb"][0] =static_cast<int>(color.x * 255) ;
                    cfg->json["main_decoration"]["rgb"][1] = static_cast<int>(color.y * 255);
                    cfg->json["main_decoration"]["rgb"][2] = static_cast<int>(color.z * 255);
                    if (!alpha_bar)
                        color.w = 1.0f;
                    cfg->json["main_decoration"]["rgb"][3] = static_cast<int>(color.w * 255);
                    DataSender(client, BakeColorChange ,cfg);
                };
                ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel); 
                clear_color = color;
            }         
            ImGui::End();

            if (saveFile) {
                ImGui::Begin(u8"保存成功", 0, window_flags);
                {
                    if (ImGui::Button(u8"确定")) {
                        saveFile = false;
                    }
                }
                ImGui::End();
            }

            if (saveFileError) {
                ImGui::Begin(u8"保存失败", 0, window_flags);
                {
                    if (ImGui::Button(u8"确定")) {
                        saveFileError = false;
                    }
                }
                ImGui::End();
            }
        } 
        else 
        {
            load_module_decelaration(cfg, mode);
            cat_data_write_json_file(cfg, "config.ini");
            break;        
        }

        // Rendering
        ImGui::Render();
        int display_w, display_h;
        glfwGetFramebufferSize(window, &display_w, &display_h);
        glViewport(0, 0, display_w, display_h);
        glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
        glClear(GL_COLOR_BUFFER_BIT);
        ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

        glfwSwapBuffers(window);       
    }
    client.SendData(DisConnect, "", 0);

    // Cleanup
    ImGui_ImplOpenGL3_Shutdown();
    ImGui_ImplGlfw_Shutdown();
    ImGui::DestroyContext();

    glfwDestroyWindow(window);

    cat_live2d_release();
    return;
}
